package com.cambright.stack.components
{
	import com.cambright.Enumerator;
	import com.cambright.lotusroot.Component;
	import com.cambright.stack.components.layout.Element;
	import com.cambright.stack.components.layout.Margin;
	
	import flash.display.DisplayObjectContainer;
	import flash.events.Event;
	
	[ExcludeClass]
	public class LayoutComponent extends Component
	{
		private var _elementVec:Vector.<Element>;
		
		private var _width:int = int.MIN_VALUE;
		private var _height:int = int.MIN_VALUE;
		
		private var _elementChanged:Boolean = true;
		private var _marginChanged:Boolean = true;
		private function get _sizeChanged():Boolean
		{
			return _target.width != _width || _target.height != _height;
		}
		
		private var _margin:Margin = new Margin(0, 0, 0, 0);
		public function get margin():Margin
		{
			return _margin;
		}
		public function set margin(value:Margin):void
		{
			if(value.left == _margin.left &&
				value.right == _margin.right &&
				value.top == _margin.top &&
				value.bottom == _margin.bottom)
				return;
			
			_margin = value;
			_marginChanged = true;
		}
		
		private var _target:DisplayObjectContainer;
		public function get target():DisplayObjectContainer
		{
			return _target;
		}
		public function set target(value:DisplayObjectContainer):void
		{
			_target = value;
		}
		
		public function get width():int
		{
			return _width;
		}
		
		public function get height():int
		{
			return _height;
		}
		
		public function get elementEnumerator():Enumerator
		{
			return new Enumerator(_elementVec);
		}
		
		public function get elementCount():int
		{
			return _elementVec.length;
		}
		
		override protected function invoke():void
		{
			_elementVec = new Vector.<Element>();
		}
		
		override protected function start():void
		{
			
		}
		
		override protected function enable():void
		{
			_target.addEventListener(Event.RENDER, _onRender);
		}
		
		override protected function disable():void
		{
			_target.removeEventListener(Event.RENDER, _onRender);
		}
		
		override protected function dispose():void
		{
			for each(var element:Element in _elementVec)
				_target.removeChild(element.display);
			_elementVec = null;
			
			_target = null;
			_margin = null;
		}
		
		private function _onRender(event:Event):void
		{
			if(isChanged) flush();
		}
		
		public function add(element:Element):void
		{
			_elementVec.push(element);
			_target.addChild(element.display);
			_elementChanged = true;
		}
		
		public function remove(element:Element):void
		{
			var index:int = _elementVec.indexOf(element);
			_elementVec.removeAt(index);
			_target.removeChildAt(index);
			_elementChanged = true;
		}
		
		protected function flush():void 
		{
			_width = _target.width;
			_height = _target.height;
			
			if(_elementChanged)
				_elementVec.sort(_elementSortByIndex);
			_elementChanged = false;
			
			_marginChanged = false;
		}
		
		private function _elementSortByIndex(element1:Element, element2:Element):int
		{
			if(element1.index > element2.index)
				return 1;
			else if(element1.index == element2.index)
				return 0;
			else return -1;
		}
		
		protected function get isChanged():Boolean
		{
			var isChanged:Boolean = false;
			isChanged = _sizeChanged || isChanged;
			isChanged = _elementChanged || isChanged;
			isChanged = _marginChanged || isChanged;
			return isChanged;
		}
	}
}